package com.umeox.auto_update

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.umeox.base.CloseableCoroutineScope
import com.umeox.logger.UMLogger
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.io.File
import java.io.FileInputStream
import java.math.BigInteger
import java.security.MessageDigest

object AutoUpdateManager {

    /**
     * 最大支持设备
     */
    private const val MAX = 3

    /**
     * 设备携程空间
     */
    private val searchScope =
        CloseableCoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)

    private const val TAG = "AutoUpdateManager"

    private var configureInfo: AutoUpdateConfigureInfo? = null

    private var devices = mutableListOf<AutoUpdateDeviceProxy>()
    private var observable = MutableLiveData(devices)

    val devicesObservable: LiveData<MutableList<AutoUpdateDeviceProxy>> = observable

    fun getTargetDeviceName() = configureInfo!!.deviceName

    fun getTarVersion() = configureInfo!!.deviceTargetVersion

    fun getOTATargetFile() = configureInfo!!.otaFilePath

    fun setConfigureInfo(info: AutoUpdateConfigureInfo) {
        configureInfo = info
    }

    fun startOTATask() {
        UMLogger.d(TAG, "开始自动OTA任务")
        searchScope.launch(Dispatchers.Main) {
            for (i in 0 until MAX) {
                requestDeviceJoin("初始任务")
                delay(10 * 1000)
            }
        }
    }

    fun addDevice(device: AutoUpdateDevice) {
        UMLogger.d(TAG, "添加设备 ${device.mac}")
        val deviceProxy = AutoUpdateDeviceProxy(device)
        devices.add(deviceProxy)
        deviceProxy.startTask()
        notifyStatusChange()
    }

    fun notifyStatusChange() {
        observable.postValue(devices)
    }

    fun isSupport(versionName: String): Boolean {
        return configureInfo!!.deviceVersions.contains(versionName)
    }

    fun getMd5Info(): String {
        if (configureInfo == null) {
            return "未检测到配置升级信息！"
        }
        val sb = StringBuilder()
        val filePath = configureInfo!!.otaFilePath
        val deviceName = configureInfo!!.deviceName
        val zikrRingMd5 = getFileMD5(File(filePath)) ?: ""
        sb.append("$deviceName   --  $zikrRingMd5")
        return sb.toString()
    }

    private fun getFileMD5(file: File): String? {
        if (!file.isFile) {
            return null
        }
        val digest: MessageDigest?
        val `in`: FileInputStream?
        val buffer = ByteArray(1024)
        var len: Int
        try {
            digest = MessageDigest.getInstance("MD5")
            `in` = FileInputStream(file)
            while (`in`.read(buffer, 0, 1024).also { len = it } != -1) {
                digest.update(buffer, 0, len)
            }
            `in`.close()
        } catch (e: Exception) {
            e.printStackTrace()
            return null
        }
        val bigInt = BigInteger(1, digest.digest())
        return bigInt.toString(16)
    }

    fun requestDeviceJoin(reason: String) {
        DeviceSearchManager.requestDeviceJoin(reason)
    }
}